#!/bin/bash
# build_all.sh
# (c) Copyright 2014
# hdu_willsky@foxmail.com 

# Notice:
# 1.This script must location at the top directory of lichee.

function mk_error()
{
    echo -e "\033[47;31mERROR: $*\033[0m"
}

function mk_warn()
{
    echo -e "\033[47;34mWARN: $*\033[0m"
}

function mk_info()
{
    echo -e "\033[47;30mINFO: $*\033[0m"
}

# return when something wrong!
set -e

# define importance variable
LICHEE_TOP_DIR=`pwd`
LICHEE_BOOT_DIR=boot
LICHEE_BR_DIR=debian_rootfs
LICHEE_KERN_DIR=linux-3.4
LICHEE_TOOLS_DIR=tools
LICHEE_UBOOT_DIR=u-boot
LICHEE_OUT_DIR=out
# kernel module output dir
LICHEE_MOD_DIR=output/lib/modules/${KERNEL_VERSION}

LICHEE_CHIP=sun7i
LICHEE_PLATFORM=linux
KERNEL_VERSION='3.4'
CROSS_COMPILE=arm-linux-gnueabihf-
IMAGE_NAME="LINUX_${KERNEL_VERSION}_DEBIAN.img"

# make sure at the top directory of lichee
if [ ! -d ${LICHEE_BOOT_DIR} -o \
     ! -d ${LICHEE_BR_DIR} -o \
     ! -d ${LICHEE_KERN_DIR} -o \
     ! -d ${LICHEE_TOOLS_DIR} -o \
     ! -d ${LICHEE_UBOOT_DIR} ] ; then
    mk_error "You are not at the top directory of lichee."
    mk_error "Please changes to that directory."
    exit 1
fi

# export importance variable
export LICHEE_TOP_DIR
export LICHEE_BOOT_DIR
export LICHEE_BR_DIR
export LICHEE_KERN_DIR
export LICHEE_TOOLS_DIR
export LICHEE_UBOOT_DIR
export LICHEE_OUT_DIR

update_kernel_ver()
{
    if [ -r include/generated/utsrelease.h ] ; then
        KERNEL_VERSION=`cat include/generated/utsrelease.h | awk -F\" '{print $2}'`
    fi
    LICHEE_MOD_DIR=output/lib/modules/${KERNEL_VERSION}
}

# Clean all target
function mkclean()
{
	mk_info "clean out directory..."
	rm -rf ${LICHEE_OUT_DIR}
	mk_info "clean modules directory..."
	rm -rf ${LICHEE_BR_DIR}/lib/modules
	mk_info "clean uboot..."
	(make -C ${LICHEE_UBOOT_DIR} distclean CROSS_COMPILE=${CROSS_COMPILE}) 
		[ $? -ne 0 ] && mk_error "clean u-boot Failed" && return 1
	mk_info "clean kernel..."
	(make -C ${LICHEE_KERN_DIR} distclean CROSS_COMPILE=${CROSS_COMPILE})
		[ $? -ne 0 ] && mk_error "clean kernel Failed" && return 1
	mk_info "clean all target successful!"
}

# prepare dir
function prepare_dir() 
{
	if [ ! -d ${LICHEE_OUT_DIR} ] ; then
   	 	mk_info "${LICHEE_OUT_DIR} directory create..."
    		mkdir -p ${LICHEE_OUT_DIR}
	fi
}

#build u-boot
function mkuboot()
{
	mk_info "build uboot..."
	prepare_dir
	(make -j8 ${LICHEE_CHIP} -C ${LICHEE_UBOOT_DIR} CROSS_COMPILE=${CROSS_COMPILE})
		[ $? -ne 0 ] && mk_error "make u-boot Failed" && return 1
	cp -f ${LICHEE_UBOOT_DIR}/u-boot.bin ${LICHEE_OUT_DIR}
	mk_info "make u-boot successful and has copy to ${LICHEE_OUT_DIR}"
}

#build kernel 
function mkkernel() 
{
	prepare_dir
	if [ ! -f ${LICHEE_KERN_DIR}/.config ]; then
		printf "\n\033[0;31;1mCopy default config...\033[0m\n\n"
		cp ${LICHEE_KERN_DIR}/arch/arm/configs/${LICHEE_CHIP}_defconfig ${LICHEE_KERN_DIR}/.config
	fi
	
	cd ${LICHEE_KERN_DIR}

	#build kernel start
	mk_info "build kernel..."
	#make ARCH=arm CROSS_COMPILE=${CROSS_COMPILE} menuconfig
	(make ARCH=arm CROSS_COMPILE=${CROSS_COMPILE} -j8 uImage modules)
		[ $? -ne 0 ] && mk_error "make kernel Failed" && return 1

	${CROSS_COMPILE}objcopy -R .note.gnu.build-id -S -O binary vmlinux bImage
		
        update_kernel_ver
	rm -rf output
	mkdir -p ${LICHEE_MOD_DIR}
	cp bImage output/
	cp -f arch/arm/boot/[zu]Image output/
	cp .config output/
	cp -f Module.symvers ${LICHEE_MOD_DIR}
	
	#build modules start
	mk_info "build modules..."
	if [ ! -f include/generated/utsrelease.h ]; then
        	printf "Please build kernel first\n"
         	exit 1
   	fi
	(make ARCH=arm -j8 CROSS_COMPILE=${CROSS_COMPILE} INSTALL_MOD_PATH=output modules_install)
		[ $? -ne 0 ] && mk_error "make modules Failed" && return 1
	
	# nand lib
	#NAND_ROOT=drivers/mtd/nand
	#if [ -d ${NAND_ROOT}/lib ]; then
	#	echo "build nand library now"
	#	make -C modules/nand/lib clean 2> /dev/null 
	#	make -C modules/nand/lib lib install
   	#else
        # 	echo "build nand with existing library"
    	#fi
	#make -C modules/nand LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KERN_DIR} \
        #install
	
	# copy nand mod
	rm -rf rootfs/skel
	mkdir rootfs/skel
	# extract ramdisk
	gzip -dc rootfs/rootfs.cpio.gz | (cd rootfs/skel; fakeroot cpio -i ) > /dev/null
	# copy nand.ko to ramdisk	
	mkdir -p rootfs/skel/lib/modules/${KERNEL_VERSION}
	cp ${LICHEE_MOD_DIR}/kernel/drivers/block/sunxi_nand/nfd/sunxi_nand.ko rootfs/skel/lib/modules/${KERNEL_VERSION}/nand.ko
	if [ $? -ne 0 ]; then
        	mk_error "copy nand module error: $?"
        	exit 1
    	fi
	# gzip ramdisk
	rm -f rootfs.cpio.gz
	if [ -d rootfs/skel ] ; then
    		(cd rootfs/skel; find . | fakeroot cpio -o -Hnewc | gzip > ../../rootfs.cpio.gz) > /dev/null
    	else
    		echo "skel not exist"
    		exit 1
    	fi
	# remove rootfs/skel
	rm -rf rootfs/skel
	# build boot image
	mk_info "build boot image"
	../${LICHEE_TOOLS_DIR}/pack/pctools/linux/android/mkbootimg \
		--kernel output/bImage \
		--ramdisk rootfs.cpio.gz \
		--board 'sun7i' \
		--base 0x40000000 \
		-o output/boot.img
	mk_info "copy boot.img to out directory"
	cp output/boot.img ../${LICHEE_OUT_DIR}
}

# copy kernel modules to rootfs 
function copy_modules()
{
	mk_info "copy kernel modules to rootfs"
	cp -R ${LICHEE_KERN_DIR}/output/lib ${LICHEE_BR_DIR}
}

# make rootfs.ext4
function mk_rootfs_ext4()
{
	mk_info "make rootfs.ext4"
	size=$(sudo du -sm ${LICHEE_BR_DIR} | awk '{print int($1)}')
	echo "rootfs real size : ${size}"
	let size+=100
	dd if=/dev/zero of=${LICHEE_OUT_DIR}/rootfs.ext4 bs=1M count=${size}
	if [ $? == 0 ]; then 
		mkfs.ext4 -q -F ${LICHEE_OUT_DIR}/rootfs.ext4
		sudo mount -o loop ${LICHEE_OUT_DIR}/rootfs.ext4 /mnt
		sudo cp -a ${LICHEE_BR_DIR}/* /mnt
		sudo umount /mnt
		sync
		mk_info "make rootfs.ext4 success and location at ${LICHEE_OUT_DIR}"
	else
		mk_error "make rootfs.ext4 failed!" && exit 1
	fi
}
count=0
# pack to img
function pack_img() {	
	# make sure that rootfs and kernel,u-boot has compiled"
	if [ -d ${LICHEE_OUT_DIR} ] ; then
    		LICHEE_OUT_DIR=`cd ${LICHEE_OUT_DIR}; pwd`
	else
    		mk_error "build kernel rootfs and u-boot before you pack"
    		exit 1
	fi

	# find chips
	count=0
	printf "All valid chips:\n"
	for chip in $(cd ${LICHEE_TOOLS_DIR}/pack/chips/; find -mindepth 1 -maxdepth 1 -type d |sort); do
		chips[$count]=`basename ${LICHEE_TOOLS_DIR}/pack/chips/$chip`
		printf "$count. ${chips[$count]}\n"
		let count=$count+1
	done

	# select chip
	while true; do
		read -p "Please select a chip:"
		RES=`expr match $REPLY "[0-9][0-9]*$"`
		if [ "$RES" -le 0 ]; then
			echo "please use index number"
			continue
		fi
		if [ "$REPLY" -ge $count ]; then
			echo "too big"
			continue
		fi
		if [ "$REPLY" -lt "0" ]; then
			echo "too small"
			continue
		fi
		break
	done
	mk_info "selected chip is $REPLY. ${chips[$REPLY]}"
	TARGET_CHIP=${chips[$REPLY]}
	
	# find platforms
	count=0
	printf "All valid platforms:\n"
	for platform in $(cd ${LICHEE_TOOLS_DIR}/pack/chips/$TARGET_CHIP/configs/; 
	  find -mindepth 1 -maxdepth 1 -type d |sort); do
		platforms[$count]=`basename ${LICHEE_TOOLS_DIR}/pack/chips/$TARGET_CHIP/configs/$platform`
		printf "$count. ${platforms[$count]}\n"
		let count=$count+1
	done
	
	# select platform
	while true; do
		read -p "Please select a platform:"
		RES=`expr match $REPLY "[0-9][0-9]*$"`
		if [ "$RES" -le 0 ]; then
			echo "please use index number"
			continue
		fi
		if [ "$REPLY" -ge $count ]; then
			echo "too big"
			continue
		fi
		if [ "$REPLY" -lt "0" ]; then
			echo "too small"
			continue
		fi
		break
	done	
	mk_info "selected platform is $REPLY. ${platforms[$REPLY]}"
	TARGET_PLATFORM=${platforms[$REPLY]}	

	# find boards
	count=0
	printf "All valid boards(not include default):\n"
	for board in $(cd ${LICHEE_TOOLS_DIR}/pack/chips/$TARGET_CHIP/configs/$TARGET_PLATFORM/; 
	  find -mindepth 1 -maxdepth 1 -type d |grep -v default|sort); do
		boards[$count]=`basename ${LICHEE_TOOLS_DIR}/pack/chips/$TARGET_CHIP/configs/$TARGET_PLATFORM/$board`
		printf "$count. ${boards[$count]}\n"
		let count=$count+1
	done

	# select board
	while true; do
		read -p "Please select a board:"
		RES=`expr match $REPLY "[0-9][0-9]*$"`
		if [ "$RES" -le 0 ]; then
			echo "Please use index number"
			continue
		fi
		if [ "$REPLY" -ge $count ]; then
			echo "too big"
			continue
		fi
		if [ "$REPLY" -lt "0" ]; then
			echo "too small"
			continue
		fi
		break
	done
	TARGET_BOARD=${boards[$REPLY]}
	mk_info "selected board is $REPLY. $TARGET_BOARD"

	# pack prepare
	printf "\n\n"
	echo "Pack infomation:"
	echo "Target Chip: $TARGET_CHIP"
	echo "Target Platform: $TARGET_PLATFORM"
	echo "Target Board: $TARGET_BOARD"
	# set pack tools env
	export PATH=${LICHEE_TOOLS_DIR}/pack/pctools/linux/mod_update:${LICHEE_TOOLS_DIR}/pack/pctools/linux/eDragonEx:${LICHEE_TOOLS_DIR}/pack/pctools/linux/fsbuild200:${LICHEE_TOOLS_DIR}/pack/pctools/linux/android:$PATH
	# copy boot0 to $LICHEE_TOOLS_DIR/pack/
	cd ${LICHEE_TOOLS_DIR}/pack/
	rm -rf eFex
	rm -rf eGon
	rm -rf wboot
	cp -r chips/${TARGET_CHIP}/eFex  	. 
	cp -r chips/${TARGET_CHIP}/eGon  	.
	cp -r chips/${TARGET_CHIP}/wboot 	.
	# remake out dir
	rm -rf out/
	mkdir -p out/
	# copy fex cfg to out dir
	cp -f chips/${TARGET_CHIP}/configs/${TARGET_PLATFORM}/default/*                 out/
	cp -f chips/${TARGET_CHIP}/configs/${TARGET_PLATFORM}/${TARGET_BOARD}/*.fex     out/
	cp -f chips/${TARGET_CHIP}/configs/${TARGET_PLATFORM}/${TARGET_BOARD}/*.cfg		out/ 2>> /dev/null
	# parse sys_partition.fex and sys_config.fex
	[ -f out/sys_partition.fex ] && script_parse -f out/sys_partition.fex
   	[ -f out/sys_config.fex ] && script_parse -f out/sys_config.fex
   	# copy other files
   	cp -rf eFex/split_xxxx.fex wboot/bootfs wboot/bootfs.ini out/
    cp -f eGon/boot0_nand.bin   out/boot0_nand.bin
    cp -f eGon/boot1_nand.bin   out/boot1_nand.fex
    cp -f eGon/boot0_sdcard.bin out/boot0_sdcard.fex
    cp -f eGon/boot1_sdcard.bin out/boot1_sdcard.fex

    cd out/
    stan_cmd cp ${LICHEE_OUT_DIR}/u-boot.bin bootfs/linux/
	# set pack information to cfg file   
    sed -i 's/\\bootfs/\/bootfs/g' bootfs.ini
    sed -i 's/\\\\/\//g' image.cfg
    sed -i 's/imagename/;imagename/g' image.cfg

    echo "imagename = ${IMAGE_NAME}" >> image.cfg
    echo "" >> image.cfg
	# now packing
	mk_info "Packing for $TARGET_PLATFORM"
	
	busybox unix2dos sys_config.fex
    busybox unix2dos sys_partition.fex
    pack_cmd script sys_config.fex
    pack_cmd script sys_partition.fex
    
    cp sys_config.bin bootfs/script.bin
    pack_cmd update_mbr sys_partition.bin 4
    
    pack_cmd update_boot0 boot0_nand.bin   sys_config.bin NAND
    pack_cmd update_boot0 boot0_sdcard.fex sys_config.bin SDMMC_CARD
    pack_cmd update_boot1 boot1_nand.fex   sys_config.bin NAND
    pack_cmd update_boot1 boot1_sdcard.fex sys_config.bin SDMMC_CARD
    
    pack_cmd fsbuild bootfs.ini split_xxxx.fex
    mv bootfs.fex bootloader.fex
    
    u_boot_env_gen env.cfg env.fex
    
    ln -s ${LICHEE_OUT_DIR}/boot.img boot.fex

    ln -s ${LICHEE_OUT_DIR}/rootfs.ext4 rootfs.fex
    
    pack_cmd dragon image.cfg sys_partition.fex
    
    if [ -e ${IMAGE_NAME} ]; then
        mv ${IMAGE_NAME} ../${IMAGE_NAME}
        echo '----------image is at----------'
        echo -e '\033[0;31;1m'
        echo ${LICHEE_TOOLS_DIR}/pack/${IMAGE_NAME}
        echo -e '\033[0m'
    fi

    cd ..
}

# parse the command-line
if [ "$1" = "pack" ] ; then
    pack_img
    exit 0
fi
if [ "$1" = "clean" ] ; then
    mkclean
    exit 0
fi
if [ "$1" = "uboot" ] ; then
    mkuboot
    exit 0
fi
if [ "$1" = "kernel" ] ; then
    mkkernel
    exit 0
fi
if [ "$1" = "rootfs" ] ; then
    copy_modules
    mk_rootfs_ext4
    exit 0
fi
if [ "$1" = "all"]; then
	mkclean
	mkuboot
	mkkernel
	copy_modules
	mk_rootfs_ext4
	pack_img
fi


